
#ifndef PARTROBOTAGENT_H
#define PARTROBOTAGENT_H

#pragma once


#include "Agent.h"
#include "Lock.h"
#include "Sema.h"
#include "KitInterface.h"
#include "Nest.h"
#include "Qt\qdatetime.h"

#include "PartRobot.h"
#include "GUIPartRobot.h"
#include "TableInterface.h"
#include "KitRobot.h"
#include "Table.h"
#include "Kit.h"
class PartRobot;
class Agent;
class Lock;
class Sema;
class Nest;
class GUIPartRobot;
class TableInterface;
class KitInterface;
class KitRobot;
/**
 * @class	PartRobotAgent
 *
 * @brief	Part robot agent.
 *
 * @author	Andrew Erridge
 * @date	11/8/2011
 */

class PartRobotAgent : public PartRobot, public Agent
{
public:
	PartRobotAgent(std::string);
	~PartRobotAgent(void);

	// Non-norms
	void handleBreak();
	void handleFix();
	// ------------------------------------------------------------------------------------

	//public messages
	virtual void msgMakeKit(KitInterface *kit);
	virtual void msgImStable(Nest *nest);
	virtual void msgYouCanGoToTable();
	virtual void msgPartsDumped();
	virtual void msgPartRetrieved(int handLocation, PartType type);
	virtual std::string toString() const;

	//public getters & setters
	void setTable(TableInterface*);
	void setKitRobot(KitRobot*);
	void addNest(Nest*);
	virtual void setGUI(GUIPartRobotInterface*);
	virtual GUIPartRobot* getGUI(void);

//protected: //testing purposes
	
	virtual bool pickAndExecuteAnAction(void); //scheduler

	// actions
	void pickUp(PartType pt, int freeHandLocation, Nest* n);
	void askToDumpLoad();
	void dumpLoad();
	void allocatePartsNeededToNests(KitInterface*);
	
	// helper functions
	bool handsAreEmpty();
	bool handsAreFull();
	bool kitsAreInProgress();
	bool isPartTypeBeingMade(PartType pt);

	//inner classes & types
	enum NestState { STABLE = 1000, UNSTABLE };
	enum KitState { WAITING = 2000, IN_PROGRESS, FINISHED };
	enum TableStatus { ACCESSIBLE = 3000, INACCESSIBLE, PENDING };

	struct MyKit
	{
		KitInterface* kit;
		KitState state;
	};

	struct MyNest
	{
		Nest* nest;
		NestState state;
		PartType partTypeHeld;
		bool isMakingUsefulPart;
		int approxPartsIncoming;
		QDateTime lastMadeUnstable;
	};
	
	//Data
	Sema partsDumpedSema;
	Sema partRetrievedSema;
	Lock partsTypesNeededLock;
	
	std::vector<MyKit> myKits;
	std::vector<MyNest> myNests; //externally set
	std::vector<PartType> partTypesNeeded;
	std::vector<PartType> partsInHands;
	TableStatus tableStatus;
	TableInterface *sharedDataTable;  //externally set
	KitRobot* kitRobot; //externally set
	GUIPartRobotInterface* gui;
};
#endif